//
//  State_InGameLayer.m
//  FunnyRacing
//
//  Created by vy phan on 15/03/2011.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#import "State_InGameLayer.h"
#import "GraphicConstant.h"
//#define _DEBUG_BOX_

@implementation State_InGameLayer
- (id)init
{
	self = [super init];
	if (self != nil) {
		CGSize winsize = [[CCDirector sharedDirector]winSize];
		screenW = winsize.width;
		screenH = winsize.height;
		
		map = [[Map alloc]initWithMapName:@"city"];
		map.position = ccp(screenW / 2, screenH / 2);
#ifndef _DEBUG_BOX_
		[self addChild:map z:0];
#endif
		
		car = [[Car alloc]initCarWithType:WCAR];
		car.position = ccp(screenW / 2, screenH / 2 + 100);
		car.tag = 1;
#ifndef _DEBUG_BOX_
		[self addChild:car z:1];
#endif
		
		dpad = [[DPad alloc]init];
		dpad.position = CGPointZero;
		[self addChild:dpad z:2];
		
		// box2d engine
		// Create b2 world
        b2Vec2 gravity = b2Vec2(0.0f, 0.0f);
        bool doSleep = false;
        _world = new b2World(gravity, doSleep);
		
		
		_contactListener = new MyContactListener();
		_world->SetContactListener(_contactListener);
        // Enable debug draw
        _debugDraw = new GLESDebugDraw( PTM_RATIO );
        _world->SetDebugDraw(_debugDraw);
		
        uint32 flags = 0;
        flags += b2DebugDraw::e_shapeBit;
        _debugDraw->SetFlags(flags);
		
		[self addBoxBodyForSprite:car];
		[self addBoxBodyForSprite:(CCSprite*)map];
		[self schedule:@selector(tick:)];
		[self schedule:@selector(controlCar:) interval:1.0/60];
		
	}
	return self;
}

- (void)tick:(ccTime) dt {
	
    // Updates the physics simulation for 10 iterations for velocity/position
    _world->Step(dt, 10, 10);
	
    // Loop through all of the Box2D bodies in our Box2D world..
    for(b2Body *b = _world->GetBodyList(); b; b=b->GetNext()) {
		
        // See if there's any user data attached to the Box2D body
        // There should be, since we set it in addBoxBodyForSprite
        if (b->GetUserData() != NULL) {            
            
            // We know that the user data is a sprite since we set
            // it that way, so cast it...
            CCSprite *sprite = (CCSprite *)b->GetUserData();
            
            // Convert the Cocos2D position/rotation of the sprite to the Box2D position/rotation
            b2Vec2 b2Position = b2Vec2(sprite.position.x/PTM_RATIO,
                                       sprite.position.y/PTM_RATIO);
            float32 b2Angle = -1 * CC_DEGREES_TO_RADIANS(sprite.rotation);
            
            // Update the Box2D position/rotation to match the Cocos2D position/rotation
            b->SetTransform(b2Position, b2Angle);
			
        }
		
	}
	// Loop through all of the box2d bodies that are currently colliding, that we have
    // gathered with our custom contact listener...
    std::vector<b2Body *>toDestroy; 
    std::vector<MyContact>::iterator pos;
    for(pos = _contactListener->_contacts.begin(); pos != _contactListener->_contacts.end(); ++pos) {
        MyContact contact = *pos;
        
        // Get the box2d bodies for each object
        b2Body *bodyA = contact.fixtureA->GetBody();
        b2Body *bodyB = contact.fixtureB->GetBody();
        if (bodyA->GetUserData() != NULL && bodyB->GetUserData() != NULL) {
			// chay tam tam
//            CCSprite *spriteA = (CCSprite *) bodyA->GetUserData();
//            CCSprite *spriteB = (CCSprite *) bodyB->GetUserData();
            car.rotation += 5;
			if (car.speed > 1) {
				car.speed -= 1;
			}
			
        }        
    }
	
//    // Loop through all of the box2d bodies we wnat to destroy...
//    std::vector<b2Body *>::iterator pos2;
//    for(pos2 = toDestroy.begin(); pos2 != toDestroy.end(); ++pos2) {
//        b2Body *body = *pos2;     
//        
//        // See if there's any user data attached to the Box2D body
//        // There should be, since we set it in addBoxBodyForSprite
//        if (body->GetUserData() != NULL) {
//            
//            // We know that the user data is a sprite since we set
//            // it that way, so cast it...
//            CCSprite *sprite = (CCSprite *) body->GetUserData();
//            
//            // Xu ly sau va cham
//            //[self removeChild:sprite cleanup:YES];
//			car.rotation += 60;
//        }
//        
//        // Destroy the Box2D body as well
//        //_world->DestroyBody(body);
//    }
	
}
-(void)controlCar:(ccTime)dt{
		// khong bam chi het thi toc do se cham dan lai//
//	if (dpad.direction == -1){
//		if (car.speed > 0.5) {
//			car.speed -= (float)car.speed*car.speedDecay;
//		}
//		else {
//			car.speed = 0;
//		}
//	}
		switch (dpad.direction) {
			case DPAD_UP:
				if (car.speed < car.maxSpeed) {
					car.speed += car.accel;
				}
				break;
			case DPAD_DOWN:
				//if (car.speed > 0) {
					car.speed = -car.backSpeed;
				//}
				//else {
					//car.speed = 0;
				//}

				break;
			case DPAD_LEFT:
			{
				car.rotation -= car.rotationStep*((float)car.speed / car.maxSpeed);
				break;
			}
			case DPAD_RIGHT:
			{
				car.rotation += car.rotationStep*((float)car.speed / car.maxSpeed);
				break;
			}
			default:
				break;
		}
		//we calculate the two components of speed (X axis and Y axis) - we have already discussed this part of the function above
		// toa do tren iphone (0,0) nam o doc duoi ben trai nen phai la * -1
		float carX = -sin([car rotation]*(M_PI/180))*car.speed;
		float carY = -cos([car rotation]*(M_PI/180))*car.speed;
	
		printf("carX = %f\n", carX);
		printf("carY = %f\n", carY);
		// xét lại tọa độ sau mỗi lần tính toán	
		car.position = ccp(car.position.x + carX, car.position.y + carY);
		map.position = ccp(map.position.x - carX, map.position.y - carY);
	
}

- (void)addBoxBodyForSprite:(CCSprite *)sprite {
    
    b2BodyDef spriteBodyDef;
    spriteBodyDef.type = b2_dynamicBody;
    spriteBodyDef.position.Set(sprite.position.x/PTM_RATIO, sprite.position.y/PTM_RATIO);
    spriteBodyDef.userData = sprite;
    b2Body *spriteBody = _world->CreateBody(&spriteBodyDef);
	
    b2PolygonShape spriteShape;
    /*spriteShape.SetAsBox(sprite.contentSize.width/PTM_RATIO/2,
	 sprite.contentSize.height/PTM_RATIO/2);*/
	
	if (sprite.tag == 1) {
		int num = 4;
		b2Vec2 verts[] = {b2Vec2(9.0f / PTM_RATIO, -27.8f / PTM_RATIO),
			b2Vec2(10.4f / PTM_RATIO, 26.7f / PTM_RATIO),
			b2Vec2(-10.8f / PTM_RATIO, 26.7f / PTM_RATIO),
			b2Vec2(-10.4f / PTM_RATIO, -26.4f / PTM_RATIO)};
        spriteShape.Set(verts, num);
		
		b2FixtureDef spriteShapeDef;
		spriteShapeDef.shape = &spriteShape;
		spriteShapeDef.density = 10.0;
		spriteShapeDef.isSensor = true; 
		spriteBody->CreateFixture(&spriteShapeDef);
	}
	else {
		// city.png
		//NSMutableArray *vertArray = [[NSMutableArray alloc] init];
		//row 1, col 1
		int num = 5;
		//b2Vec2* vertArray[] = {
//			{
//				b2Vec2(162.8f / PTM_RATIO, -144.5f / PTM_RATIO),
//				b2Vec2(260.6f / PTM_RATIO, -45.3f / PTM_RATIO),
//				b2Vec2(257.7f / PTM_RATIO, 17.5f / PTM_RATIO),
//				b2Vec2(-273.7f / PTM_RATIO, 19.0f / PTM_RATIO),
//				b2Vec2(-276.6f / PTM_RATIO, -140.1f / PTM_RATIO)
//			},
//			{
//				b2Vec2(27.2f / PTM_RATIO, 22.6f / PTM_RATIO),
//				b2Vec2(-270.4f / PTM_RATIO, 227.2f / PTM_RATIO),
//				b2Vec2(-270.4f / PTM_RATIO, 23.9f / PTM_RATIO)
//			},
//			nil
//		
//		};
		b2Vec2 verts[] = {b2Vec2(162.8f / PTM_RATIO, -144.5f / PTM_RATIO),
			b2Vec2(260.6f / PTM_RATIO, -45.3f / PTM_RATIO),
			b2Vec2(257.7f / PTM_RATIO, 17.5f / PTM_RATIO),
			b2Vec2(-273.7f / PTM_RATIO, 19.0f / PTM_RATIO),
			b2Vec2(-276.6f / PTM_RATIO, -140.1f / PTM_RATIO)};
		spriteShape.Set(verts, num);
		b2FixtureDef spriteShapeDef;
		spriteShapeDef.shape = &spriteShape;
		spriteShapeDef.density = 10.0;
		spriteShapeDef.isSensor = true; 
		spriteBody->CreateFixture(&spriteShapeDef);
		
		//row 1, col 1
		num = 3;
		b2Vec2 verts2[] = {b2Vec2(27.2f / PTM_RATIO, 22.6f / PTM_RATIO),
			b2Vec2(-270.4f / PTM_RATIO, 227.2f / PTM_RATIO),
			b2Vec2(-270.4f / PTM_RATIO, 23.9f / PTM_RATIO)};
		spriteShape.Set(verts2, num);
		b2FixtureDef spriteShapeDef2;
		spriteShapeDef2.shape = &spriteShape;
		spriteShapeDef2.density = 10.0;
		spriteShapeDef2.isSensor = true; 
		spriteBody->CreateFixture(&spriteShapeDef2);
		
		//row 1, col 1
		num = 5;
		b2Vec2 verts3[] = {b2Vec2(-271.5f / PTM_RATIO, 384.3f / PTM_RATIO),
			b2Vec2(-181.3f / PTM_RATIO, 258.4f / PTM_RATIO),
			b2Vec2(70.5f / PTM_RATIO, 136.2f / PTM_RATIO),
			b2Vec2(260.3f / PTM_RATIO, 141.9f / PTM_RATIO),
			b2Vec2(256.5f / PTM_RATIO, 384.3f / PTM_RATIO)};
		
		spriteShape.Set(verts3, num);
		b2FixtureDef spriteShapeDef3;
		spriteShapeDef3.shape = &spriteShape;
		spriteShapeDef3.density = 10.0;
		spriteShapeDef3.isSensor = true; 
		spriteBody->CreateFixture(&spriteShapeDef3);
	}

    
}
- (void)spriteDone:(id)sender {
    
    // This selector is called from CCCallFuncN, and it passes the object the action is
    // run on as a parameter.  We know it's a sprite, so cast it as that!
    CCSprite *sprite = (CCSprite *)sender;
    
    // Loop through all of the Box2D bodies in our Box2D world...
    // We're looking for the Box2D body corresponding to the sprite.
    b2Body *spriteBody = NULL;
    for(b2Body *b = _world->GetBodyList(); b; b=b->GetNext()) {
        
        // See if there's any user data attached to the Box2D body
        // There should be, since we set it in addBoxBodyForSprite
        if (b->GetUserData() != NULL) {
            
            // We know that the user data is a sprite since we set
            // it that way, so cast it...
            CCSprite *curSprite = (CCSprite *)b->GetUserData();
            
            // If the sprite for this body is the same as our current
            // sprite, we've found the Box2D body we're looking for!
            if (sprite == curSprite) {
                spriteBody = b;
                break;
            }
        }
    }
    
    // If we found the body, we want to destroy it since the cat is offscreen now.
    if (spriteBody != NULL) {
        _world->DestroyBody(spriteBody);
    }
    
    // And of course we need to remove the Cocos2D sprite too.
    [self removeChild:sprite cleanup:YES];
    
}
- (void)collision:(ccTime)dt
{
	CGPoint carPointLeft = ccp(car.position.x - CAR_WIDTH / 2, car.position.y);
	CGPoint carPointRight = ccp(car.position.x + CAR_WIDTH / 2, car.position.y);
	CGPoint carPointFront = ccp(car.position.x, car.position.y + CAR_HEIGHT / 2);
	CGPoint carPointBack = ccp(car.position.x, car.position.y - CAR_HEIGHT / 2);
	
}

-(void) draw
{
	glDisable(GL_TEXTURE_2D);
	glDisableClientState(GL_COLOR_ARRAY);
	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
	
	_world->DrawDebugData();
	
	glEnable(GL_TEXTURE_2D);
	glEnableClientState(GL_COLOR_ARRAY);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
}

- (void)dealloc
{
	NSLog(@"GameScene dealloc");
	[map release];
	[car release];
	[dpad release];
	delete _world;
	[super dealloc];
}
@end
